import * as WebSocket from 'ws';
import { EventEmitter } from 'events';
import { RemoteConfig } from '../remote';

export class WebSocketServer extends EventEmitter {
  private wss: WebSocket.Server | null = null;
  private readonly clients: Map<WebSocket.WebSocket, { address: string }> = new Map();
  private readonly config: RemoteConfig;

  constructor(config: RemoteConfig) {
    super();
    this.config = config;
    console.log(`[WS_SERVER] Created with config:`, {
      hostname: config.hostname,
      port: config.port,
      hasSerializer: !!config.serializer
    });
  }

  async start(hostname: string, port: number): Promise<void> {
    return new Promise<void>((resolve, reject) => {
      try {
        console.log(`[WS_SERVER] Starting WebSocket server on ${hostname}:${port}`);
        this.wss = new WebSocket.Server({ 
          port: port 
        });

        this.wss.on('listening', () => {
          console.log(`[WS_SERVER] WebSocket server listening on port ${port}`);
          resolve();
        });

        this.wss.on('error', (error) => {
          console.error(`[WS_SERVER] Server error:`, error);
          reject(error);
        });

        this.wss.on('connection', (ws, req) => {
          const clientAddress = req.socket.remoteAddress || 'unknown';
          const clientPort = req.socket.remotePort || 0;
          const clientId = `${clientAddress}:${clientPort}`;
          
          console.log(`[WS_SERVER] New connection from ${clientId}`);
          this.clients.set(ws, { address: clientId });
          
          // 发送握手确认消息
          try {
            const handshakeMessage = {
              type: 'handshake',
              address: `${this.config.hostname}:${this.config.port}`,
              serverTime: Date.now()
            };
            ws.send(JSON.stringify(handshakeMessage));
            console.log(`[WS_SERVER] Sent handshake to client ${clientId}`);
          } catch (error) {
            console.error(`[WS_SERVER] Error sending handshake:`, error);
          }

          ws.on('message', async (data: WebSocket.Data) => {
            try {
              console.log(`[WS_SERVER] Received message from ${clientId}, data type: ${typeof data}, size: ${data.toString().length} bytes`);
              
              // 解析消息
              let parsedMessage;
              try {
                const strData = data.toString();
                const previewLength = Math.min(strData.length, 300);
                console.log(`[WS_SERVER] Raw message data (preview): ${strData.substring(0, previewLength)}${strData.length > previewLength ? '...' : ''}`);
                parsedMessage = JSON.parse(strData);
                console.log(`[WS_SERVER] Successfully parsed message:`, {
                  type: parsedMessage.type, 
                  targetPID: parsedMessage.targetPID,
                  hasSender: !!parsedMessage.senderPID,
                  hasMessage: !!parsedMessage.message,
                  messageId: parsedMessage.messageId
                });
              } catch (error) {
                console.error(`[WS_SERVER] Failed to parse message:`, error);
                return;
              }
              
              // 处理消息
              if (this.config.serializer) {
                try {
                  console.log(`[WS_SERVER] Using serializer to deserialize message`);
                  const message = this.config.serializer.deserialize(parsedMessage);
                  console.log(`[WS_SERVER] Emitting deserialized message event`);
                  this.emit('message', message, clientId);
                } catch (error) {
                  console.error(`[WS_SERVER] Deserialization error:`, error);
                  // 尝试直接发出解析后的消息
                  console.log(`[WS_SERVER] Falling back to parsed JSON message`);
                  this.emit('message', parsedMessage, clientId);
                }
              } else {
                // 无序列化器，直接使用解析后的消息
                console.log(`[WS_SERVER] No serializer configured, emitting parsed JSON directly`);
                this.emit('message', parsedMessage, clientId);
              }
              
              // 发送确认接收消息
              if (parsedMessage.messageId) {
                try {
                  const ackMessage = {
                    type: 'ack',
                    messageId: parsedMessage.messageId,
                    timestamp: Date.now()
                  };
                  ws.send(JSON.stringify(ackMessage));
                  console.log(`[WS_SERVER] Sent ACK for message ${parsedMessage.messageId}`);
                } catch (error) {
                  console.error(`[WS_SERVER] Error sending ACK:`, error);
                }
              }
              
            } catch (error) {
              console.error(`[WS_SERVER] Error handling message:`, error);
            }
          });

          ws.on('close', (code, reason) => {
            console.log(`[WS_SERVER] Client ${clientId} disconnected: ${code} - ${reason || 'No reason'}`);
            this.clients.delete(ws);
            this.emit('clientDisconnected', clientId);
          });

          ws.on('error', (error) => {
            console.error(`[WS_SERVER] Client error for ${clientId}:`, error);
            // 考虑关闭这个客户端连接
            try {
              ws.close();
            } catch (closeError) {
              console.error(`[WS_SERVER] Error closing connection:`, closeError);
            }
            this.clients.delete(ws);
          });

          // 通知新客户端连接
          this.emit('clientConnected', clientId);
        });

      } catch (error) {
        console.error(`[WS_SERVER] Error starting server:`, error);
        reject(error);
      }
    });
  }

  send(address: string, message: any): void {
    console.log(`[WS_SERVER] Attempting to send message to client ${address}`);
    
    // 查找目标客户端
    let targetClient: WebSocket.WebSocket | null = null;
    for (const [client, info] of this.clients.entries()) {
      if (info.address === address) {
        targetClient = client;
        break;
      }
    }
    
    if (!targetClient) {
      console.warn(`[WS_SERVER] Client ${address} not found, attempting broadcast`);
      
      // 如果找不到特定客户端，尝试广播
      let serializedMessage: string;
      
      try {
        if (this.config.serializer) {
          console.log(`[WS_SERVER] Using serializer for message`);
          serializedMessage = this.config.serializer.serialize(message);
        } else {
          console.log(`[WS_SERVER] Using JSON.stringify for message`);
          serializedMessage = JSON.stringify(message);
        }
        
        console.log(`[WS_SERVER] Broadcasting message to all ${this.clients.size} clients`);
        let sentCount = 0;
        
        for (const client of this.clients.keys()) {
          if (client.readyState === WebSocket.OPEN) {
            try {
              client.send(serializedMessage);
              sentCount++;
            } catch (error) {
              console.error(`[WS_SERVER] Error sending broadcast to client:`, error);
            }
          }
        }
        
        console.log(`[WS_SERVER] Message broadcast to ${sentCount}/${this.clients.size} clients`);
        
      } catch (error) {
        console.error(`[WS_SERVER] Error serializing broadcast message:`, error);
        throw error;
      }
      
      return;
    }
    
    // 发送到目标客户端
    if (targetClient.readyState !== WebSocket.OPEN) {
      console.error(`[WS_SERVER] Client ${address} connection not open (state: ${targetClient.readyState})`);
      throw new Error(`Client connection not open: ${address}`);
    }
    
    try {
      let serializedMessage: string;
      
      if (this.config.serializer) {
        console.log(`[WS_SERVER] Using serializer for message to ${address}`);
        serializedMessage = this.config.serializer.serialize(message);
      } else {
        console.log(`[WS_SERVER] Using JSON.stringify for message to ${address}`);
        serializedMessage = JSON.stringify(message);
      }
      
      targetClient.send(serializedMessage);
      console.log(`[WS_SERVER] Message sent successfully to ${address}`);
      
    } catch (error) {
      console.error(`[WS_SERVER] Error sending message to ${address}:`, error);
      throw error;
    }
  }

  broadcast(message: any): void {
    console.log(`[WS_SERVER] Broadcasting message to all clients`);
    
    try {
      let serializedMessage: string;
      
      if (this.config.serializer) {
        serializedMessage = this.config.serializer.serialize(message);
      } else {
        serializedMessage = JSON.stringify(message);
      }
      
      console.log(`[WS_SERVER] Serialized broadcast message, length: ${serializedMessage.length}`);
      let sentCount = 0;
      
      for (const client of this.clients.keys()) {
        if (client.readyState === WebSocket.OPEN) {
          try {
            client.send(serializedMessage);
            sentCount++;
          } catch (error) {
            console.error(`[WS_SERVER] Error sending to client:`, error);
          }
        }
      }
      
      console.log(`[WS_SERVER] Message broadcast to ${sentCount}/${this.clients.size} clients`);
      
    } catch (error) {
      console.error(`[WS_SERVER] Error serializing broadcast message:`, error);
      throw error;
    }
  }

  close(): void {
    console.log(`[WS_SERVER] Closing WebSocket server`);
    
    if (this.wss) {
      for (const client of this.clients.keys()) {
        try {
          client.close();
        } catch (error) {
          console.error(`[WS_SERVER] Error closing client:`, error);
        }
      }
      
      this.wss.close(() => {
        console.log(`[WS_SERVER] Server closed successfully`);
      });
      
      this.wss = null;
      this.clients.clear();
    }
  }

  isStarted(): boolean {
    return this.wss !== null;
  }

  getClientCount(): number {
    return this.clients.size;
  }
} 